import { parseBooleanParam } from '../../util/param'

export default class WechatApi {
  private app
  private config
  private apiUrl
  private timeout
  private maxTimeout
  private defaultCallbackUrl
  private errorHandler

  constructor (app, aipUrl?: string) {
    this.app = app
    this.config = app.config.wechatApi

    this.apiUrl = aipUrl || this.config.defaultApiUrl
    this.timeout = this.config.timeout
    this.maxTimeout = this.config.maxTimeout
    this.defaultCallbackUrl = this.config.defaultCallbackUrl

    this.errorHandler = (id, err) => {
      return Promise.reject(err)
    }
  }

  setErrorHandler (func) {
    this.errorHandler = func
  }

  setCallbackUrl (id, url = this.defaultCallbackUrl) {
    this.app.logger.debug(`[egg-wechat-api] setCallbackUrl param id:`, id, `${this.apiUrl}/${id}/callback-url`, url)
    return this.app.curl(`${this.apiUrl}/${id}/callback-url`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: { url: url }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] setCallbackUrl result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getCallbackUrl (id) {
    this.app.logger.debug(`[egg-wechat-api] setCallbackUrl param id:`, id, `${this.apiUrl}/${id}/callback-url`)
    return this.app.curl(`${this.apiUrl}/${id}/callback-url`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getCallbackUrl result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  login (id, withQrcode = '1', withOwner = '1') {
    this.app.logger.debug(`[egg-wechat-api] login param id:`, id, `${this.apiUrl}/${id}/status`)
    return this.app.curl(`${this.apiUrl}/${id}/status`, {
      timeout: [this.timeout, this.maxTimeout],
      dataType: 'json',
      data: { with_qrcode: parseBooleanParam(withQrcode), with_owner: parseBooleanParam(withOwner) },
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] login result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  logout (id) {
    return this.app.curl(`${this.apiUrl}/${id}/logout`, {
      timeout: [this.timeout, this.maxTimeout],
      contentType: 'json',
      dataType: 'json',
      method: 'POST'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] logout result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getOwner (id) {
    return this.app.curl(`${this.apiUrl}/${id}/owner`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getOwner result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  sayToSelf (id, content, msgType) {
    return this.app.curl(`${this.apiUrl}/${id}/say`, {
      timeout: this.timeout,
      contentType: 'json',
      dataType: 'json',
      method: 'POST',
      data: { content, msg_type: msgType }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] sayToSelf result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getContacts (id) {
    return this.app.curl(`${this.apiUrl}/${id}/contacts`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getContacts result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getFriends (id) {
    return this.app.curl(`${this.apiUrl}/${id}/friends`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      this.app.logger.debug(`[egg-wechat-api] getFriends result`, data.length)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getContact (id, contactId) {
    return this.app.curl(`${this.apiUrl}/${id}/friends/${contactId}`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getContact result`, data)

      if (!data || !data.name) {
        throw new Error('[egg-wechat-api] get contact wrong')
      }

      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  findContact (id, alias, limit) {
    return this.app.curl(`${this.apiUrl}/${id}/friends-find`, {
      timeout: this.timeout,
      dataType: 'json',
      data: {
        alias,
        limit
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getContact result`, data)

      if (!data || !data.name) {
        throw new Error('[egg-wechat-api] get contact wrong')
      }

      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  patchContact (id, contactId, type, alias) {
    return this.app.curl(`${this.apiUrl}/${id}/friends/${contactId}`, {
      timeout: this.timeout,
      contentType: 'json',
      dataType: 'json',
      method: 'POST',
      data: { type, alias }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getContact result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  postMessage (id, to, content, msgType = 'text', mentionList) {
    this.app.logger.debug(`[egg-wechat-api] postMessage id=${id} to=${to} content=${content} msgType=${msgType} mentionList=${mentionList}`)
    return this.app.curl(`${this.apiUrl}/${id}/messages`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: {
        to,
        content,
        msg_type: msgType,
        mention_list: mentionList
      },
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] postMessage result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getRooms (id, withFriends = '1') {
    return this.app.curl(`${this.apiUrl}/${id}/rooms`, {
      timeout: this.timeout,
      dataType: 'json',
      data: { with_friends: parseBooleanParam(withFriends) }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getRooms result`, data.length)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getRoom (id, roomId, refresh) {
    refresh = parseBooleanParam(refresh)
    this.app.logger.debug(`[egg-wechat-api] getRoom id=${id} roomId=${roomId} refresh=${refresh}`)
    return this.app.curl(`${this.apiUrl}/${id}/rooms/${roomId}`, {
      timeout: this.timeout,
      dataType: 'json',
      data: {
        refresh: refresh
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getRoom result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  findRoom (id, topic) {
    return this.app.curl(`${this.apiUrl}/${id}/rooms-find`, {
      timeout: this.timeout,
      dataType: 'json',
      data: {
        topic: topic
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getRoom result`, data)
      return data
    })
  }

  getRoomFriends (id, roomId) {
    return this.app.curl(`${this.apiUrl}/${id}/rooms/${roomId}/friends`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      this.app.logger.debug(`[egg-wechat-api] getRoomFriends result`, data.length)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  createRoom (id, ids, topic) {
    return this.app.curl(`${this.apiUrl}/${id}/rooms`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: {
        ids,
        topic
      },
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] createRoom result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  patchRoom (id, roomId, type, topic) {
    return this.app.curl(`${this.apiUrl}/${id}/rooms/${roomId}`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'PATCH',
      data: {
        type,
        topic
      },
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] patchRoom result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  roomAdd (id, roomId, userIds) {
    return this.app.curl(`${this.apiUrl}/${id}/rooms/${roomId}/friends`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: {
        user_ids: userIds
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] roomAdd result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  roomDel (id, roomId, userIds) {
    return this.app.curl(`${this.apiUrl}/${id}/rooms/${roomId}/friends`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: {
        user_ids: userIds
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] roomDel result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  getfriendRequests (id) {
    return this.app.curl(`${this.apiUrl}/${id}/friend-requests`, {
      timeout: this.timeout,
      dataType: 'json'
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] getfriendRequests result`, data)
      return data
    })
  }

  postfriendRequest (id, contactId, hello) {
    return this.app.curl(`${this.apiUrl}/${id}/friend-request/${contactId}`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: {
        hello
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] friendRequestAccept result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }

  friendRequestAccept (id, contactId, ticket) {
    return this.app.curl(`${this.apiUrl}/${id}/friend-request/accept`, {
      timeout: this.timeout,
      dataType: 'json',
      contentType: 'json',
      method: 'POST',
      data: {
        contact_id: contactId,
        ticket
      }
    }).then((result) => {
      let data = result.data
      if (typeof data.err_code !== 'undefined' && data.err_code !== 0) {
        throw new Error(data.err_msg)
      }
      // this.app.logger.debug(`[egg-wechat-api] friendRequestAccept result`, data)
      return data
    }).catch((err) => {
      return this.errorHandler(id, err)
    })
  }
}
